﻿using SQLite;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using TabbedTemplate.Models;

namespace TabbedTemplate.Services
{
    /// <summary>
    /// 收藏存储。
    /// </summary>
    public class FavoriteStorage : IFavoriteStorage
    {
        /******** 公开变量 ********/

        /// <summary>
        /// 数据库名。
        /// </summary>
        public const string DbName = "favoritedb.sqlite3";
        /// <summary>
        /// 收藏存储已更新事件。
        /// </summary>
        public event EventHandler<FavoriteStorageUpdatedEventArgs> Updated;


        /******** 私有变量 ********/

        /// <summary>
        /// 偏好存储。
        /// </summary>
        private IPreferenceStorage _preferenceStorage;

        /// <summary>
        /// 收藏数据库路径。
        /// </summary>
        public static readonly string StoreDbPath =
            Path.Combine(
                Environment.GetFolderPath(Environment.SpecialFolder
                    .LocalApplicationData), DbName);

        /// <summary>
        /// 数据库连接影子变量。
        /// </summary>
        private SQLiteAsyncConnection _connection;

        /// <summary>
        /// 数据库连接。
        /// </summary>
        private SQLiteAsyncConnection Connection =>
            _connection ??
            (_connection = new SQLiteAsyncConnection(StoreDbPath));

        /******** 继承方法 ********/

        /// <summary>
        /// 是否已经初始化。
        /// </summary>
        public bool Initialized() =>
            _preferenceStorage.Get(FavoriteStorageConstants.VersionKey, -1) ==
            FavoriteStorageConstants.Version;

        /// <summary>
        /// 初始化。
        /// </summary>
        public async Task InitializeAsync()
        {
            await Connection.CreateTableAsync<Favorite>();
            ////打开文件流
            //using var dbFileStream =
            //    new FileStream(StoreDbPath, FileMode.Create);

            ////打开资源流
            //using var dbAssertStream = Assembly.GetExecutingAssembly()
            //    .GetManifestResourceStream(DbName);

            ////将资源流中的内容拷贝到文件流（拷贝到用户的物理文件夹）
            //await dbAssertStream.CopyToAsync(dbFileStream); //精简
            _preferenceStorage.Set(FavoriteStorageConstants.VersionKey,
                FavoriteStorageConstants.Version);
        }

        /// <summary>
        /// 获取一个收藏 。
        /// </summary>
        /// <param name="storeUid">店铺id。</param>
        public async Task<Favorite> GetFavoriteAsync(string storeUid) =>
            await Connection.Table<Favorite>()
                .FirstOrDefaultAsync(p => p.StoreUid == storeUid);

        /// <summary>
        /// 获得所有收藏。
        /// </summary>
        public async Task<IList<Favorite>> GetFavoritesAsync() =>
            await Connection.Table<Favorite>().Where(p => p.IsFavorite)
                .ToListAsync();
        // 获取满足给定条件的店铺集合。
        /// <param name="where">Where条件。</param>
        /// <param name="skip">跳过数量。</param>
        /// <param name="take">获取数量。</param>
        /// Expression 表达式 函数，参数，返回值
        /// Where 万能查找
        /// where条件，跳过多少条，返回多少条
        public async Task<IList<Favorite>> GetFavoritesAsync(int skip, int take) =>
            await Connection.Table<Favorite>().Where(p => p.IsFavorite).Skip(skip)
                .Take(take).ToListAsync();
        /// <summary>
        /// 所获得所有收藏项，包括收藏与非收藏。
        /// </summary>
        public async Task<IList<Favorite>> GetFavoriteItemsAsync() =>
            await Connection.Table<Favorite>().ToListAsync();

        /// <summary>
        /// 保存收藏。
        /// </summary>
        /// <param name="favorite">待保存的收藏。</param>
        /// <param name="generateTimestamp">是否生成时间戳。</param>
        public async Task SaveFavoriteAsync(Favorite favorite, bool generateTimestamp)
        {
            if (generateTimestamp)
            {
                favorite.Timestamp = DateTime.Now.Ticks;
            }

            await Connection.InsertOrReplaceAsync(favorite);
            Updated?.Invoke(this,
                new FavoriteStorageUpdatedEventArgs(favorite));
        }


        /******** 公开方法 ********/

        /// <summary>
        /// 收藏存储。
        /// </summary>
        /// <param name="preferenceStorage">偏好存储。</param>
        public FavoriteStorage(IPreferenceStorage preferenceStorage)
        {
            _preferenceStorage = preferenceStorage;
        }

        /// <summary>
        /// 关闭数据库。
        /// </summary>
        public async Task CloseAsync() => await Connection.CloseAsync();

        /******** 私有方法 ********/
    }

    /// <summary>
    /// 收藏存储常量。
    /// </summary>
    public static class FavoriteStorageConstants
    {
        /// <summary>
        /// 版本。
        /// </summary>
        public const string VersionKey =
            nameof(IFavoriteStorage) + "." + nameof(Version);

        /// <summary>
        /// 版本。
        /// </summary>
        public const int Version = 1;
    }
}
